﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using Framework.Data.DataType;
using Framework.Data.DataBroker;
//
//Description : Classe qui représente un champ d'un entité
//Auteur : Marc-Eric Boisvert
//Date Création : 31 mars 2008
//Révisions:
//

namespace Framework.Data.Core
{

    [Serializable()]
    public class EntityField : BaseField, IEntityField
    {


        #region "Membres"
		//TODO: Sortir le champ _schema
        //Nom du schema. La valeur par défaut est GCL
        protected string _schema = "GCL";
        //Nom de la table qui contient le champ
        protected string _tableName = string.Empty;
        //Nom du champ de la table
        protected string _databaseFieldName = string.Empty;
        //Longueur du champ
        protected int _fieldSize = 0;
        //Indicateur de clé primaire
        protected bool _isPrimaryKey = false;
        //Nombre de chiffre après le point décimal

        protected Int16 _numberPresicion = 0;
        #endregion

        #region "Construteurs"

        /// <summary>
        /// Constructeur
        /// </summary>
        /// <param name="entity">Entité auquel ce champ appartient</param>
        /// <param name="fieldValueType">Type du champ</param>
        /// <param name="tableName">Nom de la table</param>
        /// <param name="databaseFieldName">Nom du champ dans la table</param>
        /// <param name="fieldSize">Longueur du champ</param>
        /// <param name="isPrimaryKey">Indique si ce champ est une clé</param>
        /// <remarks></remarks>
        public EntityField(IBaseEntity entity, Type fieldValueType, string tableName, string databaseFieldName, int fieldSize, bool isPrimaryKey)
            : this(entity, fieldValueType, tableName, databaseFieldName, fieldSize, isPrimaryKey, false)
        {
        }

        /// <summary>
        /// Constructeur
        /// </summary>
        /// <param name="entity">Entité auquel ce champ appartient</param>
        /// <param name="fieldValueType">Type du champ</param>
        /// <param name="tableName">Nom de la table</param>
        /// <param name="databaseFieldName">Nom du champ dans la table</param>
        /// <param name="fieldSize">Longueur du champ</param>
        /// <param name="isPrimaryKey">Indique si ce champ est une clé</param>
        /// <param name="readOnly">Indique si ce champ est en lecture-seule</param>
        /// <remarks></remarks>
        public EntityField(IBaseEntity entity, Type fieldValueType, string tableName, string databaseFieldName, int fieldSize, bool isPrimaryKey, bool readOnly)
            : this(entity, fieldValueType, tableName, databaseFieldName, fieldSize, isPrimaryKey, readOnly, true)
        {
        }

        /// <summary>
        /// Constructeur
        /// </summary>
        /// <param name="entity">Entité auquel ce champ appartient</param>
        /// <param name="fieldValueType">Type du champ</param>
        /// <param name="tableName">Nom de la table</param>
        /// <param name="databaseFieldName">Nom du champ dans la table</param>
        /// <param name="fieldSize">Longueur du champ</param>
        /// <param name="isPrimaryKey">Indique si ce champ est une clé</param>
        /// <param name="readOnly">Indique si ce champ est en lecture-seule</param>
        /// <param name="displayFieldInList">Indique si ce champ est affiché dans les listes</param>
        /// <remarks></remarks>
        public EntityField(IBaseEntity entity, Type fieldValueType, string tableName, string databaseFieldName, int fieldSize, bool isPrimaryKey, bool readOnly, bool displayFieldInList)
            : this(entity, fieldValueType, tableName, databaseFieldName, fieldSize, isPrimaryKey, readOnly, displayFieldInList, true)
        {
        }

        /// <summary>
        /// Constructeur
        /// </summary>
        /// <param name="entity">Entité auquel ce champ appartient</param>
        /// <param name="fieldValueType">Type du champ</param>
        /// <param name="tableName">Nom de la table</param>
        /// <param name="databaseFieldName">Nom du champ dans la table</param>
        /// <param name="fieldSize">Longueur du champ</param>
        /// <param name="isPrimaryKey">Indique si ce champ est une clé</param>
        /// <param name="readOnly">Indique si ce champ est en lecture-seule</param>
        /// <param name="displayFieldInList">Indique si ce champ est affiché dans les listes</param>
        /// <param name="displayFieldInEditableList">Indique si ce champ est affiché dans les listes d'édition</param>
        /// <remarks></remarks>
        public EntityField(IBaseEntity entity, Type fieldValueType, string tableName, string databaseFieldName, int fieldSize, bool isPrimaryKey, bool readOnly, bool displayFieldInList, bool displayFieldInEditableList)
            : this(entity, fieldValueType, tableName, databaseFieldName, fieldSize, isPrimaryKey, readOnly, displayFieldInList, displayFieldInEditableList, tableName + "." + databaseFieldName)
        {
        }

        /// <summary>
        /// Constructeur
        /// </summary>
        /// <param name="entity">Entité auquel ce champ appartient</param>
        /// <param name="fieldValueType">Type du champ</param>
        /// <param name="tableName">Nom de la table</param>
        /// <param name="databaseFieldName">Nom du champ dans la table</param>
        /// <param name="fieldSize">Longueur du champ</param>
        /// <param name="isPrimaryKey">Indique si ce champ est une clé</param>
        /// <param name="readOnly">Indique si ce champ est en lecture-seule</param>
        /// <param name="displayFieldInList">Indique si ce champ est affiché dans les listes</param>
        /// <param name="displayFieldInEditableList">Indique si ce champ est affiché dans les listes d'édition</param>
        /// <param name="listColumnName">Nom de la colonne</param>
        /// <remarks></remarks>
        public EntityField(IBaseEntity entity, Type fieldValueType, string tableName, string databaseFieldName, int fieldSize, bool isPrimaryKey, bool readOnly, bool displayFieldInList, bool displayFieldInEditableList, string listColumnName)
            : base(entity, databaseFieldName.ToUpper(), fieldValueType, readOnly, displayFieldInList, displayFieldInEditableList, listColumnName.ToUpper())
        {
            this._tableName = tableName.ToUpper();
            this._databaseFieldName = databaseFieldName.ToUpper();
            this._fieldSize = fieldSize;
            this._isPrimaryKey = isPrimaryKey;
        }

        #endregion

        #region "IEntityField"

        public string Schema
        {
            get { return this._schema; }
            set { this._schema = value; }
        }

        public string DatabaseFieldName
        {
            get { return this._databaseFieldName; }
            set { this._databaseFieldName = value; }
        }

        public int FieldSize
        {
            get { return this._fieldSize; }
            set { this._fieldSize = value; }
        }

        public bool IsPrimaryKey
        {
            get { return this._isPrimaryKey; }
            set { this._isPrimaryKey = value; }
        }

        public string TableName
        {
            get { return this._tableName; }
            set { this._tableName = value; }
        }

        public short NumberPrecision
        {
            get { return this._numberPresicion; }
            set { this._numberPresicion = value; }
        }

        public override object OriginalValue
        {
            get
            {
            	//TODO: Créer un EntityClobField dans le projet Oracle.DataBroker
            	/*
                if ((object.ReferenceEquals(base.FieldValueType, typeof(Clob))) && ((string.IsNullOrEmpty((string)base._originalValue)) & (string.IsNullOrEmpty((string)base._value))))
                {
                    this.InitializeClobValue();
                }
                */
                return base.OriginalValue;
            }
            set { base.OriginalValue = value; }
        }

        public override object Value
        {
            get
            {
            	//TODO: Créer un EntityClobField dans le projet Oracle.DataBroker
            	/*
                if ((object.ReferenceEquals(base.FieldValueType, typeof(Clob))) && ((string.IsNullOrEmpty((string)base._originalValue)) & (string.IsNullOrEmpty((string)base._value))))
                {
                    this.InitializeClobValue();
                }
                */
                return base.Value;
            }
            set { base.Value = this.GetFormattedValue(value); }
        }

        #endregion

        #region "Methodes"
        //TODO: Créer un EntityClobField dans le projet Oracle.DataBroker
/*
        /// <summary>
        /// Procédure qui initialize la valeur du Clob lors de son accès
        /// </summary>
        /// <remarks></remarks>
        protected void InitializeClobValue()
        {
            base.InitializeValue(OracleDataBroker.Instance.ReadClobField(this));
        }
*/
        /// <summary>
        /// Procédure qui initialise la valeur du champ
        /// </summary>
        /// <param name="value">Valeur</param>
        /// <remarks></remarks>
        public override void InitializeValue(object value)
        {
            if ((this._fieldValueType.Equals(typeof(decimal)) | this._fieldValueType.Equals(typeof(double)) | this._fieldValueType.Equals(typeof(float))))
            {
                //on format la valeur
                base.InitializeValue(this.GetFormattedValue(value));
            }
            else
            {
                base.InitializeValue(value);
            }
        }

        /// <summary>
        /// Procédure qui format les valeurs des champs de type Decimal, Double et Single
        /// </summary>
        /// <param name="value">Valeur</param>
        /// <returns>Object</returns>
        /// <remarks></remarks>
        protected object GetFormattedValue(object value)
        {
            if ((this._fieldValueType.Equals(typeof(decimal))) & ((value != null) && (!value.Equals(DBNull.Value)) && (this.NumberPrecision > 0)))
            {
                //on format la valeur
                return Convert.ToDecimal(Math.Round((decimal)value, this.NumberPrecision));
            }
            else if ((this._fieldValueType.Equals(typeof(float))) & ((value != null) && (!value.Equals(DBNull.Value)) && (this.NumberPrecision > 0)))
            {
                //on format la valeur
                return Convert.ToSingle(Math.Round((Single)value, this.NumberPrecision));
            }
            else if ((this._fieldValueType.Equals(typeof(double))) & ((value != null) && (!value.Equals(DBNull.Value)) && (this.NumberPrecision > 0)))
            {
                //on format la valeur
                return Convert.ToDouble(Math.Round((double)value, this.NumberPrecision));
            }
            else
            {
                return value;
            }

        }

        #endregion


    }
}